package sdu.ltp.resolve;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;

import sdu.ltp.entity.DataBaseFascade;
import sdu.ltp.entity.ECode;
import sdu.ltp.entity.StyleInstance;
import sdu.ltp.entity.StyleMapper;
import sdu.ltp.resolve.AbstractResolver.Node;
import sdu.ltp.tool.FileBase;
import sdu.ltp.tool.InputReader;

public class ResolverArticleExecutor {

    private final AbstractResolver resolver = new TreeResolver();
    private ExecutorService eservice = Executors.newFixedThreadPool(20);
    private DataBaseFascade dbf = DataBaseFascade.newInstance();
    private final static ResolverArticleExecutor _INSTANCE = new ResolverArticleExecutor();
    public static ResolverArticleExecutor newInstance() {
	return _INSTANCE;
    }

    /**
     * 单段落执行调度
     * @param bookid
     * @param title
     * @param sort
     */
    public ResultData paragraphExecutor(int bookid,String title,int sort) {
	BaseDataMutiFactory bdmf= new BaseDataMutiFactory(new LinkedBlockingQueue<BaseData>());
	CountDownLatch latch = new CountDownLatch(1);
	Future<ResultData> resultData = eservice.submit(new ExecutorThread(bdmf, bookid, title, sort,latch));
	try {
	    ResultData data = resultData.get();
	    StatisticsTemplate.sortMap(data.getRel_models());
	    return data;
	} catch (InterruptedException e) {
	    e.printStackTrace();
	} catch (ExecutionException e) {
	    e.printStackTrace();
	}
	return null;
    }
    
    public List<Map<String,Integer>> all(int bookid) {
	List<String> titles = dbf.findTitles(bookid);
	List<Map<String,Integer>> result = new ArrayList<>();
	for(String title:titles) {
	    result.add(InputReader.readIOToBookMap(bookid, title));
	}
	return result;
    }

    /**
     * 文章执行调度
     * @param bookid
     * @param title
     */
    public ResultData articleExecutor(int bookid,String title) {

	//获取章节数
	BaseDataMutiFactory bdmf= new BaseDataMutiFactory(new LinkedBlockingQueue<BaseData>());
	int len = dbf.findsort(bookid, title);
	CountDownLatch latch = new CountDownLatch(len);
	List<ResultData> datas = new ArrayList<>();
	for(int i=0;i<len;i++) {
	    try {
		datas.add(eservice.submit(new ExecutorThread(bdmf, bookid, title, i,latch)).get());
	    } catch (InterruptedException e) {
		e.printStackTrace();
	    } catch (ExecutionException e) {
		e.printStackTrace();
	    }
	}
	try {
	    latch.await();
	} catch (InterruptedException e) {
	    e.printStackTrace();
	}
	ResultData data = new ResultData();
	data.addDatas(datas);
	StatisticsTemplate.dataOutputFile(new File(FileBase.Base_Path+"bookid_"+bookid+"_"+title), data.getRel_models());
	return data;
    }

    public List<ResultData> bookExecutor(int bookid) {
	List<ResultData> result = new ArrayList<>();
	List<String> titles = dbf.findTitles(bookid);
	for(final String title:titles) {
	    Future<ResultData> data = eservice.submit(new Callable<ResultData>() {

		@Override
		public ResultData call() {
		    return articleExecutor(bookid,title);
		}
	    });
	    try {
		result.add(data.get());
	    } catch (InterruptedException e) {
		e.printStackTrace();
	    } catch (ExecutionException e) {
		e.printStackTrace();
	    }
	}
	return result;
    }

    /**
     * 执行线程
     * @author ljh_2015
     *
     */
    class ExecutorThread implements Callable<ResultData> {

	private BaseDataMutiFactory factory;

	private int bookid;

	private String title;

	private int sort;

	private CountDownLatch latch;

	public ExecutorThread(BaseDataMutiFactory factory, int bookid,
		String title, int sort,CountDownLatch latch) {
	    this.factory = factory;
	    this.bookid = bookid;
	    this.title = title;
	    this.sort = sort;
	    this.latch = latch;
	}

	@Override
	public ResultData call() throws Exception {
	    ResultData result = new ResultData();
	    int count=1;
	    try {
		//查找数据
		factory.getBaseDatas(bookid, title, sort);
		//获取数据
		while(true) {
		    BaseData data = factory.pick();
		    if(data==null) {
			break;
		    }
		    System.out.println("======="+(count++)+": "+data.getText()+"========");
		    Map<String,List<Node>> nodes = resolver.resolveData(data);
		    List<StyleMapper> mappers = new ArrayList<>();
		    for(String key:nodes.keySet()) {
			if(key.endsWith("_1_0")) {
			    StyleInstance instance = new StyleInstance(nodes.get(key),sort,key);
			    StyleMapper mapper = instance.transforMapper();
			    mapper.setMap_code(ECode.getDefaultCodeId(mapper.getRel_lates()));
			    mappers.add(mapper);
			    //如果该文本未被作映射操作，则将其映射关系录入库中
			}
		    }
		    result.addData(mappers);
		}
		latch.countDown();
	    } catch (UnsupportedEncodingException e) {
		e.printStackTrace();
	    }
	    return result;
	}

    }

    public static void main(String[] args) {
	long start = System.currentTimeMillis();
	ResolverArticleExecutor.newInstance().bookExecutor(1);
	long end = System.currentTimeMillis();
	System.out.println("spend "+(end-start)+"ms");
    }

}
